<template>
  <Cascader
    v-if="ifShow"
    change-on-select
    placeholder="请选择"
    v-model:value="checkedVal"
    :options="options"
    :load-data="loadData"
    @change="handleChange"
  />
</template>

<script setup lang="ts">
  import { Cascader } from 'ant-design-vue';
  import mcApi from 'mc-c2b2m-operator-api';
  import { CascaderOption } from '@/interface';
  import { ref, onBeforeUnmount, watch } from 'vue';
  import { RegionModel } from 'mc-c2b2m-operator-api/types/system';

  const { SystemModule } = mcApi;
  const { RegionApi } = SystemModule;

  const ifFirst = ref<boolean>(true);
  const checkedVal = ref<string[]>([]);
  const props = defineProps({
    modelValue: {
      type: Array<string>,
      required: true,
      default: () => [],
    },
    regionKeyEnum: {
      type: Object,
      required: false,
      default: () => {
        return {
          0: 'addrProvince',
          1: 'addrCity',
          2: 'addrCounty',
          3: 'addrTownShip',
        };
      },
    },
  });
  watch(
    () => props.modelValue,
    (val) => {
      checkedVal.value = val || [];
      if (ifFirst.value && val?.length) {
        ifFirst.value = false;
        handleEchoData();
      }
    },
    {
      deep: true,
      immediate: true,
    },
  );

  const emits = defineEmits(['update:modelValue', 'checkedOptions', 'checkedDetails']);
  const checkedOptions = ref<CascaderOption[]>([]);
  function handleChange(value: any[]) {
    emits('update:modelValue', value);
    // 当前选择的地区信息的数据源
    value?.forEach?.((val, index) => {
      if (!index) {
        const find = options.value.find((find) => find.value === val);
        find && (checkedOptions.value = [find]);
      } else {
        const sourceList = checkedOptions.value?.[index - 1]?.children || [];
        const find = sourceList.find((find) => find.value === val);
        find && (checkedOptions.value[index] = find);
        checkedOptions.value.length = index + 1;
      }
    });
    emits('checkedOptions', checkedOptions.value);
    // 当前已选的地区信息的详细字段对象
    const checkDetails = {};
    value?.forEach?.((item: string, index: number) => {
      const find = checkedOptions.value.find((find) => find.value === item);
      if (find) {
        const key = props.regionKeyEnum[index];
        const { code, label, value } = find;
        checkDetails[`${key}Id`] = value;
        checkDetails[`${key}Name`] = label;
        checkDetails[`${key}LocCode`] = code;
      }
    });
    emits('checkedDetails', checkDetails);
  }

  // 回显数据时，动态加载已选取的行政区数据源，协助组件刷新数据源
  const ifShow = ref<boolean>(true);
  // 指代获取初级options完成，协助数据回显
  const ifGetOptionsDone = ref<boolean>(false);
  // 级联选择数据源
  const options = ref<CascaderOption[]>([]);
  RegionApi.getOneLevelAdminRegionList()
    .then((res: any) => {
      res?.forEach?.((item: RegionModel) => {
        const { id, name, localCode } = item;
        options.value.push({
          value: id,
          label: name,
          isLeaf: false,
          code: localCode,
        });
      });
    })
    .finally(() => (ifGetOptionsDone.value = true));

  const loadData = async (selectedOptions: any) => {
    const targetOption = selectedOptions[selectedOptions.length - 1];
    try {
      targetOption.loading = true;
      const data = await RegionApi.getSubAdminRegionList(targetOption.value);
      targetOption.children =
        data?.map?.((item: any) => {
          const { id, name, level, localCode } = item || {};
          return {
            value: id,
            label: name,
            code: localCode,
            isLeaf: level === 4, // 第四级也就是最后一级
          };
        }) || [];
      options.value = [...options.value];
      targetOption.loading = false;
    } catch {
      targetOption.loading = false;
    }
  };

  let timer: TimeoutHandle;
  function clearTimer() {
    clearTimeout(timer);
  }
  onBeforeUnmount(() => clearTimer());
  // 根据已选地区数据，动态加载对应数据源
  // 如果已存在children表示已获取过子行政区数据，则不再发起请求
  async function handleEchoData() {
    // 初次回显可能还没有加载第一级数据，递归处理等待数据返回
    if (!ifGetOptionsDone.value) {
      clearTimer();
      timer = setTimeout(() => handleEchoData(), 100);
      return;
    }
    // 没有回显数据，不作处理（例如新增操作）
    if (!props.modelValue?.length) return;
    ifShow.value = false;
    const province = options.value.find(
      (find: CascaderOption) => find.value === props.modelValue[0],
    );
    province && !province?.children?.length && (await loadData([province]));
    const city = province?.children?.find?.(
      (find: CascaderOption) => find.value === props.modelValue?.[1],
    );
    city && !city?.children?.length && (await loadData([city]));
    const county = city?.children?.find?.(
      (find: CascaderOption) => find.value === props.modelValue?.[2],
    );
    county && !county?.children?.length && (await loadData([county]));
    ifShow.value = true;
    // 触发一次change事件，处理已选数据
    handleChange(checkedVal.value);
  }
  defineExpose({ handleEchoData });
</script>
